using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using PerformanceUtility.GameDebugTools;
using ScreenManagement;

namespace InstancedGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        // Our debug system. We can keep this reference or use the DebugSystem.Instance
        // property once we've called DebugSystem.Initialize.
        DebugSystem debugSystem;

        GraphicsDeviceManager graphics;

        ScreenManager screenManager;

        // By preloading any assets used by UI rendering, we avoid framerate glitches
        // when they suddenly need to be loaded in the middle of a menu transition.
        static readonly string[] preloadAssets =
        {
            "Textures/Screens/gradient",
            "Textures/Screens/background1",
            "Textures/Screens/background2",
            "Textures/red",
            "Textures/Networking/chat_ready",
            "Textures/Networking/chat_able",
            "Textures/Networking/chat_talking",
            "Textures/Screens/splash",
            "Textures/Icons/xboxControllerStart",
            "Textures/Networking/chat_mute",
            "Sounds/TheComingNight - Nightfall",
        };

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            // These should be set to true for releases
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            graphics.SynchronizeWithVerticalRetrace = true;
            IsFixedTimeStep = false;

            // Create components
            screenManager = new ScreenManager(this);
            Components.Add(screenManager);
            //Components.Add(new MessageDisplayComponent(this));
            //Components.Add(new GamerServicesComponent(this));
            Guide.SimulateTrialMode = false;
            //Guide.SimulateTrialMode = true;

            // Activate the first screens
            //screenManager.AddScreen(new HowToPlayScreen(), PlayerIndex.One);
            screenManager.AddScreen(new IntroScreen(), null);

            // Listen for invite notification events.
            //NetworkSession.InviteAccepted += (sender, e)
            //    => NetworkSessionComponent.InviteAccepted(screenManager, e);

            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // initialize the debug system with the game and the name of the font 
            // we want to use for the debugging
            debugSystem = DebugSystem.Initialize(this, "Fonts/debugFont");

            // register a new command that lets us exit
            debugSystem.DebugCommandUI.RegisterCommand(
                "exit",                 // Name of command
                "exit application",     // Description of command
                ExitCommand);
            debugSystem.DebugCommandUI.RegisterCommand(
                "quit",                 // Name of command
                "exit application",     // Description of command
                ExitCommand);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            foreach (string asset in preloadAssets)
            {
                Content.Load<object>(asset);
            }
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // tell the TimeRuler that we're starting a new frame. you always want
            // to call this at the start of Update
            // Start measuring time for "Update".
            debugSystem.TimeRuler.StartFrame();
            debugSystem.TimeRuler.BeginMark("Update", Color.Blue);

            base.Update(gameTime);

            // Stop measuring time for "Update".
            debugSystem.TimeRuler.EndMark("Update");
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            // Start measuring time for "Draw".
            debugSystem.TimeRuler.BeginMark("Draw", Color.Yellow);

            GraphicsDevice.Clear(Color.Black);

            base.Draw(gameTime);

            // Stop measuring time for "Draw".
            debugSystem.TimeRuler.EndMark("Draw");
        }

        /// <summary>
        /// This method is called from DebugCommandHost when the user types the 'exit'
        /// command into the command prompt. This is registered with the command prompt
        /// through the DebugCommandUI.RegisterCommand method we called in Initialize.
        /// </summary>
        void ExitCommand(IDebugCommandHost host, string command, IList<string> arguments)
        {
            this.Exit();
        }

    }
}
